package gqz.mvvm.view.custom;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import java.text.DecimalFormat;

/**
 * Created by Administrator on 2017/12/6.
 * 圆形进度条，有刻度，波浪，渐变，前景背景，文本
 * 待完善：对外接口补齐；上传github以便能直接引用
 */

public class CircleProgress extends View {

    private final String TAG = "CircleProgress--";

    private Context context;
    private Paint paint;
    private Paint paintRect, paintFront, paintBack, paintText, paintScale, paintWave;

    private int width, height, halfW, halfH;

    private Path path, limitPath;//波浪路径
    private int waveX, waveX2, waveY;//波浪起始坐标
    private int waveH;//波峰高度
    private int waveGrowth;//波浪增长
    private int waveSpeed = 5, waveSpeed2 = 10;//波浪速度
    private int timeStep = 20;//时间间隔

    private RectF rectf;//圆环边界
    private int rectW = 600, rectH = rectW;
    private float cx, cy, cr;//圆心坐标和圆环半径
    private float ratio = 360.0f / 100.0f;// 360/100 比例
    private float sweepAngle = 0;// 绘制圆弧的角度,0-360
    private int progress = 0;// 进度0-100
    private int paintWidth = 50;//画笔宽度
    private int textSize = 100;//文本大小
    private boolean isNeedScale = true;//是否绘制刻度
    //Color
    private int scaleColor = Color.WHITE;//刻度颜色
    private int backColor = Color.rgb(0xcc, 0xcc, 0xcc);// 背景色
    private int frontColor = Color.rgb(0xff, 0x00, 0x00);// 前景色
    private int waveColor = Color.argb(0xaa, 0x38, 0xa8, 0xC7);// 波浪色 38A8C7
    private int waveColor2 = Color.argb(0xaa, 0x20, 0x91, 0xb7);// 波浪色 2091B7
    private SweepGradient sweepGradient;//渐变
    private int[] gradientColors = {Color.GREEN, Color.YELLOW, Color.RED};

    public CircleProgress(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        initPaint();

        path = new Path();
        limitPath = new Path();
    }

    private void initPaint() {
        //参考线
//        paint = new Paint();
//        paint.setAntiAlias(true);//抗锯齿
//        paint.setDither(true);//抖动
//        paint.setColor(0xff000000);
//        paint.setStyle(Paint.Style.FILL);
//        paint.setStrokeWidth(3);
        //边界画笔
        paintRect = new Paint();
        paintRect.setAntiAlias(true);//抗锯齿
        paintRect.setDither(true);//抖动
        paintRect.setColor(Color.rgb(0xee, 0xee, 0xee));
        paintRect.setStyle(Paint.Style.STROKE);
        paintRect.setStrokeWidth(paintWidth);
        //圆弧背景画笔
        paintBack = new Paint();
        paintBack.setAntiAlias(true);//抗锯齿
        paintBack.setDither(true);//抖动
        paintBack.setColor(backColor);
        paintBack.setStyle(Paint.Style.STROKE);
        paintBack.setStrokeCap(Paint.Cap.ROUND);
        paintBack.setStrokeWidth(paintWidth);
        //圆弧前景画笔
        paintFront = new Paint();
        paintFront.setAntiAlias(true);//抗锯齿
        paintFront.setDither(true);//抖动
        paintFront.setColor(frontColor);
        paintFront.setStyle(Paint.Style.STROKE);
//        paintFront.setStrokeCap(Paint.Cap.ROUND);
        paintFront.setStrokeWidth(paintWidth);
        //文本画笔
        paintText = new Paint();
        paintText.setAntiAlias(true);//抗锯齿
        paintText.setDither(true);//抖动
        paintText.setSubpixelText(true);//设置亚像素，优化文本，使其更清晰
        paintText.setTextSize(textSize);
        paintText.setStyle(Paint.Style.FILL);
        paintText.setColor(frontColor);
        //刻度画笔
        paintScale = new Paint();
        paintScale.setAntiAlias(true);//抗锯齿
        paintScale.setDither(true);//抖动
        paintScale.setStyle(Paint.Style.STROKE);
        paintScale.setStrokeWidth(5);
        paintScale.setColor(scaleColor);
        //波浪画笔
        paintWave = new Paint();
        paintWave.setAntiAlias(true);//抗锯齿
        paintWave.setDither(true);//抖动
        paintWave.setStyle(Paint.Style.FILL_AND_STROKE);
        paintWave.setStrokeWidth(1);
        paintWave.setColor(waveColor);
    }

    /**
     * View默认的测量规则是android:layout_width和android:layout_height为match_parent或wrap_content时，是填充全屏的。
     * MeasureSpec（测量要求/测量说明）
     * 在View的android:layout_width和android:layout_height的值（match_parent或wrap_content）就是onMeasure()两个参数。
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        Log.v(TAG, "modeW:" + widthMode + " modeH:" + heightMode + " sizeW:" + widthSize + " sizeH:" + heightSize);
        int width = rectW;
        int height = rectH;
        // MeasureSpec.Mode: EXACTLY  AT_MOST  UNSPECIFIED(少用)
        // EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
        // AT_MOST:表示子布局限制在一个最大值内，一般为WARP_CONTENT
        // UNSPECIFIED:表示子布局想要多大就多大
        // MeasureSpec.Size 是父容器为子容器提供的大小
        // 当MODE为AT_MOST时，SIZE大小为父容器所能提供的最大值。
        // 当MODE为EXACTLY时，SIZE为父容器提供的限制值。
        // 当MODE为UNSPECIFIED时，大小为0，SIZE完全由子容器的大小决定。
        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = Math.min(width, widthSize);
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = Math.min(height, heightSize);
        }

        this.width = width;
        this.height = height;
        this.halfW = width / 2;
        this.halfH = height / 2;
        int w = rectW / 10 * 9;
        int h = w;
        rectf = new RectF(getRect(halfW - w / 2, halfH - h / 2, halfW + w / 2, halfH + h / 2));
        //圆心坐标和半径
        cx = rectf.centerX();
        cy = rectf.centerY();
        cr = rectf.width() / 2;

        textSize = width / 6;
        waveX = waveX2 = -width;
        waveY = height;
        waveH = height / 15;
        waveGrowth = height / 100;

        sweepGradient = new SweepGradient(width / 2, height / 2, gradientColors, null);
        //通过旋转来处理Paint.Cap.ROUND导致的结束色的尾巴
        Matrix matrix = new Matrix();
        matrix.setRotate(-3, width / 2, height / 2);
        sweepGradient.setLocalMatrix(matrix);

        setMeasuredDimension(width, height);
    }

    private Rect getRect(int left, int top, int right, int bottom) {
        Rect rect = new Rect(left, top, right, bottom);
        return rect;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        Log.v(TAG, "onDraw: this.w=" + this.getWidth() + "  this.h=" + this.getHeight());

        //中心参考线
//        canvas.drawLine(0, halfH, width, halfH, paint);
//        canvas.drawLine(halfW, 0, halfW, height, paint);
        //圆弧范围 0ms-1ms
        long s = System.currentTimeMillis();
        canvas.drawRect(rectf, paintRect);
        //绘制波浪 1ms-5ms
        drawWave(canvas, true);
        drawWave(canvas, false);
        //圆弧背景 1ms-2ms
        paintBack.setColor(backColor);
        canvas.drawArc(rectf, 0, 360, false, paintBack);//useCenter:=true时画的是扇形;startAngle=0时从3点钟位置开始顺时针画sweepAngle
        //圆弧前景 5ms-15ms
        paintFront.setColor(frontColor);
        paintFront.setShader(sweepGradient);
        canvas.save();
        canvas.rotate(-90, cx, cy);
        canvas.drawArc(rectf, 0, sweepAngle, false, paintFront);
        canvas.restore();
        //绘制文字 0ms-1ms
        String text = progress + "%";
        Rect bounds = new Rect();
        paintText.getTextBounds(text, 0, text.length(), bounds);
        int textX = halfW - bounds.width() / 2;
        int textY = halfH + bounds.height() / 2;
        paintText.setColor(frontColor);
        paintText.setTextSize(textSize);
        canvas.drawText(text, textX, textY, paintText);
        //绘制刻度 4ms-16ms
        if (isNeedScale) {
            float sx = halfW, sy = halfH - cr - paintWidth / 2;
            paintScale.setColor(Color.WHITE);
            for (int i = 0; i < 100; i++) {
                canvas.save();
                canvas.rotate(i * 3.6f, cx, cy);
                canvas.drawLine(sx, sy, sx, sy + paintWidth, paintScale);
                canvas.restore();
            }
        }
        Log.v(TAG, "useTime:" + (System.currentTimeMillis() - s));
    }

    private void drawWave(Canvas canvas, boolean dir) {
        //贝塞尔曲线rQuad（相对位置的贝塞尔曲线）
        float step = width / 4;
        path.reset();
        limitPath.reset();
        if (dir) {//画往右的波浪
            paintWave.setColor(waveColor);

            path.moveTo(waveX, waveY);
            path.rQuadTo(step, waveH, 2 * step, 0);
            path.rQuadTo(step, -waveH, 2 * step, 0);

            path.rQuadTo(step, waveH, 2 * step, 0);
            path.rQuadTo(step, -waveH, 2 * step, 0);

            path.lineTo(waveX + 2 * width, height);
            path.lineTo(waveX, height);
            path.close();

            limitPath.addCircle(cx, cy, cr - paintWidth / 2, Path.Direction.CW);
            limitPath.op(path, Path.Op.INTERSECT);
            canvas.drawPath(limitPath, paintWave);
        } else {//画往左的波浪
            paintWave.setColor(waveColor2);

            path.moveTo(waveX2, waveY);
            path.rQuadTo(step, waveH, 2 * step, 0);
            path.rQuadTo(step, -waveH, 2 * step, 0);

            path.rQuadTo(step, waveH, 2 * step, 0);
            path.rQuadTo(step, -waveH, 2 * step, 0);

            path.lineTo(waveX2 + 2 * width, height);
            path.lineTo(waveX2, height);
            path.close();

            limitPath.addCircle(cx, cy, cr - paintWidth / 2, Path.Direction.CW);
            limitPath.op(path, Path.Op.INTERSECT);
            canvas.drawPath(limitPath, paintWave);
        }
        waveMove();
        postInvalidateDelayed(20);
//        handler.sendEmptyMessageDelayed(0, timeStep);
    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            waveMove();
        }
    };

    private void waveMove() {
        waveX += waveSpeed;
        waveX2 += waveSpeed2;
        if (waveX == 0)
            waveX = -this.getWidth();
        if (waveX2 == 0)
            waveX2 = -this.getWidth();
        invalidate();
    }

    /**
     * 设置角度0~360
     *
     * @param angle
     */
    public void setSweepAngle(int angle) {
        sweepAngle = angle;
        progress = (int) (sweepAngle / ratio);
        this.waveY = this.getHeight() - progress * waveGrowth;
        invalidate();
    }

    /**
     * 设置进度0-100
     *
     * @param progress
     */
    public void setProgress(int progress) {
        if (progress >= 0 && progress <= 100) {
            this.progress = progress;
            DecimalFormat df = new DecimalFormat("#.0");
            this.sweepAngle = Float.parseFloat(df.format(progress * ratio));
            this.waveY = this.getHeight() - progress * waveGrowth;
            invalidate();
        }
    }

    //设置背景色
    public void setBackgroundColor(int color) {
        backColor = color;
        invalidate();
    }

    //设置前景色
    public void setFrontColor(int color) {
        frontColor = color;
        invalidate();
    }

    //设置文本大小
    public void setTextSize(int size) {
        textSize = size;
        invalidate();
    }

    //设置进度条宽度
    public void setWidth(int width) {
        this.rectW = this.rectH = width;//正圆
        invalidate();
    }

    //设置进度条高度
    public void setHeight(int height) {
        this.rectH = this.rectW = height;
        invalidate();
    }

    //是否需要刻度
    public void isNeedScale(boolean isNeed) {
        isNeedScale = isNeed;
        invalidate();
    }

}
